import gradio as gr  # 正确导入 Gradio 库
from PIL import Image
from sklearn.cluster import KMeans
import numpy as np

def extract_palette(image, num_colors=5):
    """
    提取图像的主色调调色板。
    Args:
        image: 上传的 PIL 图像。
        num_colors: 要提取的主色调数量。
    Returns:
        hex_colors: 颜色列表，每个颜色的十六进制表示。
        palette_img: 调色板图像预览。
    """
    # 将图像缩小以加速处理
    image = image.resize((200, 200))
    img_data = np.array(image).reshape(-1, 3)  # 拉平成一维数组
    
    # 使用 KMeans 聚类提取主色
    kmeans = KMeans(n_clusters=num_colors, random_state=0).fit(img_data)
    colors = kmeans.cluster_centers_.astype(int)
    
    # 转换为十六进制颜色表示
    hex_colors = ["#{:02x}{:02x}{:02x}".format(*color) for color in colors]
    
    # 创建调色板预览图像
    palette_img = Image.new("RGB", (50 * num_colors, 50))
    for i, color in enumerate(colors):
        Image.new("RGB", (50, 50), tuple(color)).paste(palette_img, (i * 50, 0))
    
    return hex_colors, palette_img

def analyze_image(file):
    """
    分析上传图片，并生成主色调调色板和其预览。
    Args:
        file: 上传的文件。
    Returns:
        主色调 (十六进制) 和 调色板预览图像。
    """
    image = Image.open(file).convert("RGB")  # 确保图像为 RGB 格式
    hex_colors, palette_img = extract_palette(image)
    return {"主色调 (十六进制)": hex_colors}, palette_img

# 定义 Gradio 界面
with gr.Blocks() as app:
    gr.Markdown("# 专业调色板分析网页应用")
    gr.Markdown("上传一张图片，系统将自动分析并生成调色板，包括 5 个主色调及其十六进制表示。")

    with gr.Row():
        with gr.Column():
            file_input = gr.File(label="上传图片", type="filepath")  # 将类型设置为 "filepath"
            analyze_button = gr.Button("分析图片")
        with gr.Column():
            output_text = gr.JSON(label="主色调 (十六进制)")
            output_image = gr.Image(label="调色板")

    analyze_button.click(
        analyze_image, 
        inputs=file_input, 
        outputs=[output_text, output_image]
    )

# 启动应用
app.launch()
